#include <iostream>
#include <vector>
#include <stdlib.h>

using namespace std;

class Hanoi
{
    static const unsigned MAX;
    static const char FG;
    static const char BG;
    static const unsigned INTERVAL;

    typedef vector<unsigned> Peg;
    Peg a_,b_,c_;

    void hanoi( const int size, Peg &f, Peg &t, Peg &u )
    {
        if (size <= 1) 
        {
            t.push_back(f.back());
            f.pop_back();
            print_pegs( );
        }
        else
        {
            hanoi( size-1, f, u, t );
            hanoi( 1, f, t, u );
            hanoi( size-1, u, t, f );
        }
    }

    static void print_disk(unsigned size) 
    {
        static const unsigned MAX_WIDTH=2*MAX+1;
        const unsigned st = MAX_WIDTH/2-size;
        const unsigned en = MAX_WIDTH/2+size;
        for ( unsigned col = 0; col<MAX_WIDTH; col++ )
            cout << ( col > st && col < en ? FG : BG );
    }

    void print_pegs() 
    {
        system("clear");
        for (int tier=(MAX-1); tier >= 0; tier-- ) 
        {
            print_disk( a_.size() > (unsigned)tier ? a_[tier] : 0 );
            print_disk( b_.size() > (unsigned)tier ? b_[tier] : 0 );
            print_disk( c_.size() > (unsigned)tier ? c_[tier] : 0 );
            cout << endl;
        }
        usleep(INTERVAL);
    }

public:

    Hanoi(int size)
    {
        for ( int i=size; i>0; i-- ) a_.push_back(i);
    }

    void run() 
    {
        print_pegs();
        while ( 1 ) {
            sleep(1);
            hanoi( a_.size(), a_, b_, c_ );
            sleep(1);
            hanoi( b_.size(), b_, c_, a_ );
            sleep(1);
            hanoi( c_.size(), c_, a_, b_ );
        }
    }
};

const unsigned Hanoi::MAX = 10;
const char Hanoi::FG = 'X';
const char Hanoi::BG = ' ';
const unsigned Hanoi::INTERVAL = 12500;

int main ( int argc, char *argv[] )
{
    Hanoi h(10);
    h.run();
}
